#include "zos_config.h"


#ifdef BOARD_USING_CMIOT

#include "cmiot.h"
#include "zos.h"


//注册业务消息队列
zos_mq_t cmiot_context_mq = ZOS_NULL; //上下行报文消息队列
zos_mq_t cmiot_event_mq = ZOS_NULL; //event事件消息队列

//注册cmiot任务句柄
zos_task_t cmiot_task_handle = ZOS_NULL;

//引用回调函数
extern zos_err_t cmiot_close_callback(void);
extern zos_err_t cmiot_observer_notify_rsp_callback(int msgid,int index,int flag);
extern zos_err_t cmiot_read_rsp_callback(int msgid,int insid,int resid);
extern zos_err_t cmiot_write_rsp_callback(int len,char* value);
extern zos_err_t cmiot_exec_rsp_callback(int len,char* cmd);

typedef struct cmiot_event_msg{
    int     id;        ///< event id
    int     valueType;   ///< data type
    char    data[0];     ///< data content address
}cmiot_event_msg_t;



struct cmiot_device
{
	int instance;
	int lifetime;
	int result;
	int dev_len;
	int objcount;
	int inscount;
	int observercount;
	int discovercount;
	int event_state;
	int observer_state;
	int discover_state;
	int update_state;
	int update_time;
	int read_state;
	int write_state;
	int exec_state;
	int notify_state;
	int connect_state;
	int close_state;
	int notify_ack;
};


//初始化数据流结构体
static struct cmiot_device cmiot_device_table = {0};
static struct cmiot_stream cmiot_stream_table[CMIOT_OBJECT_MAX_NUM] = {0};

//查找对应的数据流地址
cmiot_stream_t cmiot_get_stream(int objid,int insid,int resid)
{
	zos_uint8_t i;
	for(i = 0;i < CMIOT_OBJECT_MAX_NUM;i++)
	{
		if(cmiot_stream_table[i].user_state)
		{
			if(cmiot_stream_table[i].objid == objid && insid == -1)
			{
				return &cmiot_stream_table[i];
			}
			else if(cmiot_stream_table[i].objid == objid && cmiot_stream_table[i].insid == insid && resid == -1)
			{
				return &cmiot_stream_table[i];
			}
			else if(cmiot_stream_table[i].objid == objid && cmiot_stream_table[i].insid == insid && cmiot_stream_table[i].resid == resid)
			{
				return &cmiot_stream_table[i];
			}
		}
	}
	return ZOS_NULL;
}


/*************************************************************
*	函数名称：	cmiot_object_init
*
*	函数功能：	初始化一个cmiot平台object数据流
*
*	入口参数：	objid:    object id
*						  insid:    instance id
*						  resid: 	resource id
*						  inscount: instance 数量
*						  bitmap:   instance bitmap
*						  atts: 	attribute count (具有Read/Write操作的object有attribute)
*						  actis:    action count (具有Execute操作的object有action)
*						  type: 	数据类型
*
*	返回参数：	object指针：成功		ZOS_NULL:失败
*
*	说明：		
************************************************************/	
cmiot_stream_t cmiot_object_init(int objid,int insid,int resid,zos_uint32_t inscount,char *bitmap,zos_uint32_t atts,zos_uint32_t acts,zos_uint32_t type)
{
	int num = 0;
	for(num = 0;num < CMIOT_OBJECT_MAX_NUM && cmiot_stream_table[num].user_state;num++);
	if(num >= CMIOT_OBJECT_MAX_NUM)
	{
		zos_printf("[cmiot] stream max error\r\n");
		return ZOS_NULL;
	}
	cmiot_stream_table[num].objid = objid;
	cmiot_stream_table[num].insid = insid;
	cmiot_stream_table[num].resid = resid;
	cmiot_stream_table[num].inscount = inscount;
	cmiot_stream_table[num].atts = atts;
	cmiot_stream_table[num].acts = acts;
	cmiot_stream_table[num].valuetype = type;
	cmiot_stream_table[num].user_state = 1;
	cmiot_device_table.dev_len++;
	strcpy(cmiot_stream_table[num].bitmap,bitmap);
	return &cmiot_stream_table[num];
}


/******************************************************
* 函数名称： cmiot_create_instance
*
*	函数功能： 创建模组实例 instance
*
* 入口参数： config_t 设备注册码
*
* 返回值： 0 成功  1失败
*
********************************************************/
zos_err_t cmiot_create_instance(void)
{
	zos_err_t res;
	cis_cloud_setting(CMIOT_SERVER_IP, 5683, ZOS_NULL);

	if(strlen((const char *)(g_softap_fac_nv->cloud_server_ip)) == 0)
	{
		zos_printf("[cmiot] error: server ip is empty. can not create cmiot\r\n");
		return -1;
	}	

	res = cis_create((char *)(g_softap_fac_nv->cloud_server_ip), (unsigned int)(g_softap_fac_nv->cloud_server_port), 0, ZOS_NULL);
	if(res != ZOS_EOK)
	{
		zos_printf("[cmiot] create cmiot error\r\n");
		return ZOS_ERROR;
	}
	return ZOS_EOK;
}


/******************************************************
* 函数名称： cmiot_add_object
*
*	函数功能： 添加 object 到模组
*
* 入口参数： 无
*
* 返回值： 0 成功  1失败
*
********************************************************/
zos_err_t cmiot_add_object(void)
{
	int i = 0,j = 0, a = 0, b = 0, state = 1;
	char resourcemap[100];
	int str_res[20];
	int status = 1,resourcecount = 0,objectcount = 0;
	int str[CMIOT_OBJECT_MAX_NUM];
	cmiot_device_table.objcount = 0;
	//循环添加 object
	for(;i < CMIOT_OBJECT_MAX_NUM;i++)
	{			
		if(cmiot_stream_table[i].user_state)
		{
			//循环查询object 并且添加到数组，用于记录，防止重复添加
			for(j = 0; j < cmiot_device_table.objcount;j++)
			{
				if(str[j] != cmiot_stream_table[i].objid)
					state = 1;
				else 
				{
					state = 0;		
					break;
				}
			}
			//添加object 到模组
			if(state)
			{
				//计算resid数量并保存
				for(a = 0; a < CMIOT_OBJECT_MAX_NUM; a++)
				{
					if(cmiot_stream_table[a].user_state)
					{
						//判断当前objectid 是否为 discover objectid
						if(cmiot_stream_table[a].objid == cmiot_stream_table[i].objid)
						{
							//判断当前 resourceid 是否上报过
							for(b = 0; b < resourcecount; b++)
							{
								//如果 resourceid没有上报过
								if(str_res[b] != cmiot_stream_table[a].resid)
								{
									status=1;		//上报标识置一
								}
								else 
								{
									status=0;
									break;
								}									
							}
							//判断该 resourceid 是否需要上报
							if(status)
							{
								//记录需要上报的 resourceid
								str_res[resourcecount++]=cmiot_stream_table[a].resid;
								
								//判断本次上报的 resourceid 是否为第一次找到
								if(resourcecount-1)
									sprintf(resourcemap,"%s;%d",resourcemap,cmiot_stream_table[a].resid);
								else
									sprintf(resourcemap,"%d",cmiot_stream_table[a].resid);
							}	
						}
					}
				}
				//循环打印已经记录的 resourceid
				for(b = 0; b < CMIOT_OBJECT_MAX_NUM; b++)
				{
					if(cmiot_stream_table[b].user_state)
					{
						//判断当前objectid 是否为 discover objectid
						if(cmiot_stream_table[b].objid == cmiot_stream_table[i].objid)
						{
							cmiot_stream_table[b].rescount = resourcecount;
						}
					}
				}
				resourcecount = 0;
				memset(str_res , 0 , sizeof(str_res));
				memset(resourcemap , 0 , sizeof(resourcemap));
				//记录当前object
				str[cmiot_device_table.objcount++] = cmiot_stream_table[i].objid;

				cmiot_device_table.inscount += cmiot_device_table.inscount;

				//向模组添加 objectid	
				if(cis_addobj(cmiot_stream_table[i].objid,cmiot_stream_table[i].inscount,cmiot_stream_table[i].bitmap,\
							cmiot_stream_table[i].atts,cmiot_stream_table[i].acts) != ZOS_EOK)	return ZOS_ERROR;
			}
		}
	}
	return ZOS_EOK;
}


/****************************************************
* 函数名称： cmiot_open
*
* 函数作用： 设备登录到 cmiot 平台
*
* 入口参数： 无
*
* 返回值： 0：成功   -1：失败
*****************************************************/
zos_err_t cmiot_open(void)
{
	zos_uint32_t state = ZOS_ERROR;
	cmiot_event_msg_t *rcv_msg = ZOS_NULL;

	cmiot_device_table.lifetime = CMIOT_LIFE_TIME;
	
	if(cis_reg(cmiot_device_table.lifetime) != ZOS_EOK) 
	{
		zos_printf("[cmiot] open failure\r\n");
		return ZOS_ERROR;
	}
	cmiot_device_table.connect_state = cmiot_state_run;
   	while(state != CIS_EVENT_REG_SUCCESS)
    {
        if(zos_mq_recv(cmiot_event_mq, &rcv_msg, 0, 20*1000) != ZOS_EOK)
    	{
    		zos_printf("[cmiot] recv register event timeout\r\n");
			cmiot_close();
			return ZOS_ERROR;
    	}
        if(rcv_msg->id == CIS_EVENT_REG_TIMEOUT)
        {
            zos_printf("[cmiot] register timeout\r\n");
			goto failure;
        }
		else if(rcv_msg->id == CIS_EVENT_BOOTSTRAP_FAILED)
        {
            zos_printf("[cmiot] register bs failed\r\n");
			goto failure;
        }
        state = rcv_msg->id;
        zos_free(rcv_msg);
    }
    cmiot_device_table.connect_state = cmiot_state_success;
    return ZOS_EOK;

failure:
	cmiot_close();
	zos_free(rcv_msg);
    return ZOS_ERROR;
}


/******************************************************
* 函数名称： cmiot_delete_instance
*
*	函数功能： 删除模组实例 instance
*
* 入口参数： 无
*
* 返回值：	 0：成功   -1：失败
*
********************************************************/
zos_err_t cmiot_close(void)
{
	zos_uint8_t state = ZOS_EOK;
	cmiot_event_msg_t *rcv_msg = ZOS_NULL;
	if(cmiot_device_table.connect_state == cmiot_state_init)
	{
		return ZOS_ERROR;	
	}
	if(cis_delete() != ZOS_EOK)
	{
		return ZOS_ERROR;	
	}
	while(state != CIS_EVENT_UNREG_DONE)
	{
		if(zos_mq_recv(cmiot_event_mq,&rcv_msg,0,ZOS_WAITING_FOREVER) != ZOS_EOK)
		{
			continue;
		}
		state = rcv_msg->id;
		zos_free(rcv_msg);
	}
	
	return ZOS_EOK;
}
/****************************************************
* 函数名称： cmiot_update_time
*
* 函数作用： 更新cmiot 设备维持时间
*
* 入口参数： flag :是否同时更新云端object 信息
*
* 返回值： 0：成功   -1：失败
*****************************************************/
zos_err_t cmiot_update_time(int flag)
{
	zos_uint32_t state = ZOS_ERROR;
	cmiot_event_msg_t *rcv_msg = ZOS_NULL;
	//向平台发送更新命令
	if(cis_updatelife(cmiot_device_table.lifetime,flag) != ZOS_EOK)
	{
		return  ZOS_ERROR;
	}
	while(state != CIS_EVENT_UPDATE_SUCCESS)
	{
		if(zos_mq_recv(cmiot_event_mq,&rcv_msg,0,20*1000) != ZOS_EOK)
		{
			zos_printf("[cmiot] update timeout\r\n");
			return ZOS_ERROR;
		}
		if(rcv_msg->id == CIS_EVENT_UPDATE_FAILED || rcv_msg->id == CIS_EVENT_UPDATE_TIMEOUT)
		{
			zos_printf("[cmiot] update time failure\r\n");
			zos_free(rcv_msg);
			return  ZOS_ERROR;
		}
		zos_free(rcv_msg);
		state = rcv_msg->id;
	}
	return ZOS_EOK;
	
}
/*************************************************************
*	函数名称：	cmiot_quick_start
*
*	函数功能：	一键连接到cmiot平台
*
*	入口参数：	无
*
*	返回参数：	0：成功   1：失败
*
*	说明：		
************************************************************/	
zos_err_t cmiot_quick_start(void)
{
	cmiot_event_msg_t *rcv_msg = ZOS_NULL;
	int state = ZOS_ERROR;
	if(cmiot_create_instance() !=  ZOS_EOK)	 //创建 instance
	{
		zos_printf("[cmiot] create instance failure\r\n");
		return ZOS_ERROR;
	}
	if(cmiot_add_object() != ZOS_EOK)							//创建 object
	{
		zos_printf("[cmiot] add objece failure\r\n");
		return ZOS_ERROR;
	}

	if(cmiot_open() != ZOS_EOK)	
		return ZOS_ERROR;

   	while(state != CIS_EVENT_UPDATE_SUCCESS)
    {
        if(zos_mq_recv(cmiot_event_mq, &rcv_msg, 0, 20*1000) != ZOS_EOK)
    	{
    		zos_printf("[cmiot] recv observe discover event timeout\r\n");
			goto failure;
    	}
        if(rcv_msg->id == CIS_EVENT_NOTIFY_FAILED)
        {
            zos_printf("[cmiot] notify observe failed\r\n");
			zos_free(rcv_msg);
			goto failure;
        }
        state = rcv_msg->id;
        zos_free(rcv_msg);
    }
    cmiot_device_table.connect_state = cmiot_state_success;
    zos_printf("[cmiot] register success\r\n");
    return ZOS_EOK;

failure:
	cmiot_close();
	return ZOS_ERROR;
}

/****************************************************
* 函数名称： cmiot_notify
*
* 函数作用： notify 设备数据到平台（无ACK）
*
* 入口参数： stream：object结构体		len：消息长度		data：消息内容		flag：消息标识		
*
* 返回值： 0 成功	-1失败
*****************************************************/
zos_err_t cmiot_notify(cmiot_stream_t stream,int len,cmiot_value_t data,int index,int flag)
{
	char buf[20];
	char *value = &buf;
	if(stream->valuetype == cmiot_value_string || stream->valuetype == cmiot_value_opaque)
	{
		value = (char *)data;
		if(len == 0)
		{
			len = strlen(data);
		}
	}
	else if(stream->valuetype == cmiot_value_integer)	
	{
		sprintf(buf,"%d",data->int_value);
		len = 4; 	
	}				
	else if(stream->valuetype == cmiot_value_float)
	{
		sprintf(buf,"%f",data->float_value);
		len = 4; 
	}				
	else if(stream->valuetype == cmiot_value_bool)
	{
		sprintf(buf,"%d",data->bool_value);	
		len = 1; 
	}
	// ACK 增加一次
	cmiot_device_table.notify_ack++;						
	//当ACK超过5000 时，清空一次
	if(cmiot_device_table.notify_ack > 5000)
		cmiot_device_table.notify_ack = 1;
	if(cis_notify_sync(-1,stream->objid,stream->insid,stream->resid,stream->valuetype,len,value,index,flag,\
						cmiot_device_table.notify_ack) != ZOS_EOK)
	{
		zos_printf("[cmiot] notify data error\r\n");
		return ZOS_ERROR;
	}
	return ZOS_EOK;	
}

/****************************************************
* 函数名称： cmiot_notify_with_ack
*
* 函数作用： notify 设备数据到平台（带ACK应答判断）
*
* 入口参数： stream：object结构体		len：消息长度		data：消息内容		flag：消息标识		
*
* 返回值： 0 成功	-1失败
*****************************************************/
zos_err_t cmiot_notify_with_ack(cmiot_stream_t stream,int len,cmiot_value_t data,int index,int flag)
{
	char *buf = ZOS_NULL;
	if(stream->valuetype == cmiot_value_opaque)
	{
		buf = zos_zalloc(len + 20);
	}
	else
	{
		buf = zos_zalloc(len * 2 + 20);
	}
	
	zos_uint32_t state = ZOS_ERROR;
	cmiot_event_msg_t *rcv_msg = ZOS_NULL;

	if(stream->valuetype  ==  cmiot_value_string || stream->valuetype  ==  cmiot_value_opaque)
	{
		sprintf(buf,"%s",data);
		if(len == 0)
		{
			len = strlen(data);
		}
	}
	else if(stream->valuetype == cmiot_value_integer)	
	{
		sprintf(buf,"%d",data->int_value);
		len = 4; 	
	}				
	else if(stream->valuetype == cmiot_value_float)
	{
		sprintf(buf,"%f",data->float_value);
		len = 4; 
	}				
	else if(stream->valuetype == cmiot_value_bool)
	{
		sprintf(buf,"%d",data->bool_value);
		len = 1; 
	}
	// ACK 增加一次
	cmiot_device_table.notify_ack++;						
	//当ACK超过5000 时，清空一次
	if(cmiot_device_table.notify_ack>5000)
		cmiot_device_table.notify_ack = 1;
	if(cis_notify_sync(-1,stream->objid,stream->insid,stream->resid,stream->valuetype,len,buf,index,flag,\
						cmiot_device_table.notify_ack) != ZOS_EOK)
	{
		zos_printf("[cmiot] notify data error\r\n");
		zos_free(buf);
		return ZOS_ERROR;
	}
	zos_free(buf);
	while(state != CIS_EVENT_NOTIFY_SUCCESS)
	{
		if(zos_mq_recv(cmiot_event_mq,&rcv_msg,0,5*1000) != ZOS_EOK)
		{
			zos_printf("[cmiot] notify timeout\r\n");
			return ZOS_ERROR;
		}
		if(rcv_msg->id == CIS_EVENT_NOTIFY_FAILED)
		{
			zos_printf("[cmiot] notify error\r\n");
			zos_free(rcv_msg);
			return  ZOS_ERROR;
		}
		zos_free(rcv_msg);
		state = rcv_msg->id;
	}
	return ZOS_EOK;	
}
/****************************************************
* 函数名称： cmiot_get_connect
*
* 函数作用： 获取cmiot 平台连接状态
*
* 入口参数： 无
*
* 返回值： 0：连接成功	     1：连接已断开
*****************************************************/
zos_err_t cmiot_get_connect(void)
{
	if(cmiot_device_table.connect_state == cmiot_state_success)
		return ZOS_EOK;

		return ZOS_ERROR;
}
/****************************************************
* 函数名称： cmiot_get_object_read
*
* 函数作用： 查询当前object 是否收到平台read消息
*
* 入口参数： stream：object结构体
*
* 返回值： 0：收到	  1：没收到
*****************************************************/
zos_err_t cmiot_get_object_read(cmiot_stream_t stream)
{
	if(stream->read_state == 10)
		return ZOS_EOK;

	return ZOS_ERROR;
}
/****************************************************
* 函数名称： cmiot_get_object_write
*
* 函数作用： 查询当前object 是否收到平台write消息
*
* 入口参数： stream：object结构体
*
* 返回值： 0：收到	  1：没收到
*****************************************************/
zos_err_t cmiot_get_object_write(cmiot_stream_t stream)
{
	if(stream->write_state == 10)
		return ZOS_EOK;
	return ZOS_ERROR;
}
/****************************************************
* 函数名称： cmiot_get_object_exec
*
* 函数作用： 查询当前object 是否收到平台exec消息
*
* 入口参数： object：object分组	
*
* 返回值： 0：收到	  1：没收到
*****************************************************/
zos_err_t cmiot_get_object_exec(cmiot_stream_t stream)
{
	if(stream->exec_state == 10)
		return ZOS_EOK;	
	return ZOS_ERROR;
}

/****************************************************
* 函数名称： cmiot_get_object_exec
*
* 函数作用： 查询当前object 是否收到平台exec消息
*
* 入口参数： object：object分组	
*
* 返回值： 0：收到	  1：没收到
*****************************************************/
zos_err_t cmiot_get_observe_notify(cmiot_stream_t stream)
{
	if(stream->observe_notify_state == 10)
		return ZOS_EOK;
		
	return ZOS_ERROR;
}
/****************************************************
* 函数名称： cmiot_read_rsp
*
* 函数作用： 响应cmiot read 操作
*
* 入口参数： msgid：消息ID		
*
*						 result：读写状态
*	
*						 stream：object 结构体
*
*						 len：上报的消息长度
*
*						 data：上报的消息值			
*
*						 index：指令序列号
*
*						 flag: 消息标识
*
* 返回值： 0：成功   -1：失败
*****************************************************/
zos_err_t cmiot_read_rsp(zos_uint32_t msgid,zos_uint32_t result,cmiot_stream_t stream,zos_uint32_t len,cmiot_value_t data,zos_uint32_t index,zos_uint32_t flag)
{
	char buf[20];
	char *value = &buf;
	if(stream->valuetype == cmiot_value_string || stream->valuetype == cmiot_value_opaque)
	{
		value = (char *)data;
		if(len == 0)
		{
			len = strlen(data);
		}
	}
	else if(stream->valuetype == cmiot_value_integer)
	{
		sprintf(buf,"%d",data->int_value);		
		len = 4;
	}
	else if(stream->valuetype == cmiot_value_float)
	{
		sprintf(buf,"%f",data->float_value);
		len = 4;
	}
	else if(stream->valuetype == cmiot_value_bool)
	{
		sprintf(buf,"%d",data->bool_value);
		len = 1;
	}
	if(cis_read_rsp(msgid,result,stream->objid,stream->insid,stream->resid,stream->valuetype,len,value,index,flag) != ZOS_EOK)
	{
		return ZOS_ERROR;
	}
	stream->read_state = 0;
	return ZOS_EOK;
}

static int cmiot_discover_callback(int msgid,int objid)
{
	char resourcemap[100];
	int str_res[20];
	int i = 0,j = 0,status = 1,resourcecount = 0,objectcount = 0;
	
	for(i = 0; i < CMIOT_OBJECT_MAX_NUM; i++)
	{
		if(cmiot_stream_table[i].user_state)
		{
			//判断当前objectid 是否为 discover objectid
			if(cmiot_stream_table[i].objid==objid)
			{
				//判断当前 resourceid 是否上报过
				for(j=0;j<resourcecount;j++)
				{
					//如果 resourceid没有上报过
					if(str_res[j] != cmiot_stream_table[i].resid)
					{
						status=1;		//上报标识置一
					}
					else 
					{
						status=0;
						break;
					}									
				}
				//判断该 resourceid 是否需要上报
				if(status)
				{
					//记录需要上报的 resourceid
					str_res[resourcecount++]=cmiot_stream_table[i].resid;
					
					//判断本次上报的 resourceid 是否为第一次找到
					if(resourcecount-1)
						sprintf(resourcemap,"%s;%d",resourcemap,cmiot_stream_table[i].resid);
					else
						sprintf(resourcemap,"%d",cmiot_stream_table[i].resid);
				}	
			}
		}
	}
	//循环打印已经记录的 resourceid
	for(j = 0; j < CMIOT_OBJECT_MAX_NUM; j++)
	{
		if(cmiot_stream_table[j].user_state)
		{
			//判断当前objectid 是否为 discover objectid
			if(cmiot_stream_table[j].objid==objid)
			{
				cmiot_stream_table[j].rescount = resourcecount;
			}
		}
	}
	if(cis_discover_rsp(-1, objid, 1, strlen(resourcemap), resourcemap) != ZOS_EOK)
	{
		zos_printf("[cmiot] discover error\r\n");
		return ZOS_ERROR;
	}
	return ZOS_EOK;
}

static zos_err_t cmiot_observe_callback(int msgid, int flag, int objid, int insid, int resid, int result)
{
	int i,j,k,index = 0;
	cmiot_stream_t stream = ZOS_NULL;
	//response observe result
	cis_observe_rsp(msgid, result);

	//Notify all instance and all resource of the specified object id
	if((flag & URI_FLAG_INSTANCE_ID) == 0)
	{
		stream = cmiot_get_stream(objid, -1, -1);
		index = stream->inscount * stream->rescount -1;
		for(i = 0; i < stream->inscount; i++)
		{
			for (j = 0; j < CMIOT_OBJECT_MAX_NUM ; j++)
			{
				if(cmiot_stream_table[j].objid == objid && cmiot_stream_table[j].insid == i)
				{
	
					if(index == (cmiot_stream_table[i].rescount -1)  && index != 0)
					{
						flag = 1;
					}
					else if(index == 0)
					{
						flag = 0;
					}
					else
					{
						flag = 2;
					}
				}
				cmiot_stream_table[i].observe_notify_state = 10;
				cmiot_observer_notify_rsp_callback(msgid,index,flag);
				cmiot_stream_table[i].observe_notify_state = 0;
				index -- ;
			}
		}
	}
	//Notify all resource of the specified objectID and instance id
	else if((flag & URI_FLAG_RESOURCE_ID) == 0)
	{
		
		stream = cmiot_get_stream(objid, insid, -1);
		index = (stream->rescount -1);
		for(i = 0; i < CMIOT_OBJECT_MAX_NUM; i++)
		{
			if(cmiot_stream_table[i].objid == objid && cmiot_stream_table[i].insid == insid)
			{
				if(index == (cmiot_stream_table[i].rescount -1) && index != 0)
				{
					flag = 1;
				}
				else if(index == 0)
				{
					flag = 0;
				}
				else
				{
					flag = 2;
				}
				cmiot_stream_table[i].observe_notify_state = 10;
				cmiot_observer_notify_rsp_callback(msgid,index,flag);
				cmiot_stream_table[i].observe_notify_state = 0;
				index -- ;
			}
		}
	}
	//Notify the specified resource id
	else
	{
		for(i = 0; i < CMIOT_OBJECT_MAX_NUM; i++)
		{
			if(cmiot_stream_table[i].objid == objid && cmiot_stream_table[i].insid == insid && cmiot_stream_table[i].resid == resid)
			{
				cmiot_stream_table[i].observe_notify_state = 10;
				cmiot_observer_notify_rsp_callback(msgid,0,0);
				cmiot_stream_table[i].observe_notify_state = 0;
				return ZOS_EOK;
			}
		}
	}
	return ZOS_EOK;
}
/****************************************************
* 函数名称： cmiot_read_callback
*
* 函数作用： cmiot read 响应
*
* 入口参数： msgid	消息ID			
*	
*			objid	即将操作的objectid
*
*			insid	即将操作的 instanceid
*
*			resid 即将操作的 instanceid							
*
* 返回值： 0：成功   -1：失败
*****************************************************/
static zos_err_t cmiot_read_callback(int msgid,int objid,int insid,int resid, int flag)
{
	int i,j,k,index = 0;
	cmiot_stream_t stream = ZOS_NULL;
	
	if((flag & URI_FLAG_INSTANCE_ID) == 0)
	{
		stream = cmiot_get_stream(objid, -1, -1);
		index = stream->inscount * stream->rescount -1;
		for(i = 0; i < stream->inscount; i++)
		{
			for (j = 0; j < CMIOT_OBJECT_MAX_NUM ; j++)
			{
				if(cmiot_stream_table[j].objid == objid && cmiot_stream_table[j].insid == i)
				{
	
					if(index == (cmiot_stream_table[i].rescount -1) && index != 0)
					{
						flag = 1;
					}
					else if(index == 0)
					{
						flag = 0;
					}
					else
					{
						flag = 2;
					}
				}
				cmiot_stream_table[i].read_state = 10;
				cmiot_read_rsp_callback(msgid,index,flag);
				cmiot_stream_table[i].read_state = 0;
				index -- ;
			}
		}
	}
	else if((flag & URI_FLAG_RESOURCE_ID) == 0)
	{
		stream = cmiot_get_stream(objid, insid, -1);
		index == (stream->rescount -1);
		for(i = 0; i < CMIOT_OBJECT_MAX_NUM; i++)
		{
			if(cmiot_stream_table[i].objid == objid && cmiot_stream_table[i].insid == insid)
			{
				if(index == (cmiot_stream_table[i].rescount -1) && index != 0)
				{
					flag = 1;
				}
				else if(index == 0)
				{
					flag = 0;
				}
				else
				{
					flag = 2;
				}
				cmiot_stream_table[i].read_state = 10;
				cmiot_read_rsp_callback(msgid,index,flag);
				cmiot_stream_table[i].read_state = 0;
				index -- ;
			}
		}
	}
	else
	{
		for(i = 0; i < CMIOT_OBJECT_MAX_NUM; i++)
		{
			if(cmiot_stream_table[i].objid == objid && cmiot_stream_table[i].insid == insid && cmiot_stream_table[i].resid == resid)
			{
				cmiot_stream_table[i].read_state = 10;
				cmiot_read_rsp_callback(msgid,0,0);
				cmiot_stream_table[i].read_state = 0;
				return ZOS_EOK;
			}
		}
	}

	// read 回调函数处理失败操作
	zos_printf("[cmiot] read rsp failure\r\n");
	return  ZOS_ERROR;
}
/****************************************************
* 函数名称： cmiot_write_callback
*
* 函数作用： cmiot write 响应
*
* 入口参数： msgid：消息ID			
*	
*						 objid：即将操作的objectid
*
*						 insid：即将操作的 instanceid
*
*						 resid：即将操作的 instanceid		
*
*						 valuetype：write值类型	
*
*						 len：write值长度	
*
*						 value：write值	
*
* 返回值：0：成功   1：失败
*****************************************************/
static zos_err_t cmiot_write_callback(int msgid,int objid,int insid,int resid,int len,char *value)
{
	int i = 0,result = cmiot_state_result_Not_Found;;
		//循环检测objectid
	for(;i<cmiot_device_table.dev_len;i++)
	{
		//判断当前objectid 是否为即将要读的信息
		if(cmiot_stream_table[i].objid == objid&&cmiot_stream_table[i].insid == insid&&cmiot_stream_table[i].resid == resid)
		{
			cmiot_stream_table[i].write_state = 10;
			//进入 write 回调函数
			if(cmiot_write_rsp_callback(len,value) == ZOS_EOK)
			{
				result = cmiot_state_result_write_success;
			}
			else	//write回调函数处理失败操作
			{
				result = cmiot_state_result_Bad_Request;
				zos_printf("[cmiot] write rsp failure\r\n");
			}
			cmiot_stream_table[i].write_state = 0;
			if(cis_write_rsp(-1, 2) != ZOS_EOK) return ZOS_ERROR;
			return ZOS_EOK;
		}
	}
	//当前 objectid 不在列表中
	return ZOS_ERROR;	
}
/****************************************************
* 函数名称： cmiot_execute_rsp
*
* 函数作用： cmiot execute 响应
*
* 入口参数： msgid	消息ID			
*	
*							objid：即将操作的objectid
*
*							insid：即将操作的 instanceid
*
*							resid：即将操作的 instanceid		
*
*							len：cmd值长度	
*
*							cmd：本次cmd值	
*
* 返回值： 0：成功   -1：失败
*****************************************************/
static zos_err_t cmiot_execute_rsp(int msgid,int objid,int insid,int resid,int len,char *cmd)
{
	int i = 0,result = cmiot_state_result_Not_Found;
	
	for(;i<cmiot_device_table.dev_len;i++)
	{
		//判断当前objectid 是否为即将要读的信息
		if(cmiot_stream_table[i].objid == objid&&cmiot_stream_table[i].insid == insid&&cmiot_stream_table[i].resid == resid)
		{
			cmiot_stream_table[i].exec_state = 10;
			//进入 execute 回调函数
			if(cmiot_exec_rsp_callback(len,cmd) == ZOS_EOK)
			{
				result = cmiot_state_result_write_success;
			}
			else	//execute回调函数处理失败操作
			{
				result = cmiot_state_result_Bad_Request;
				zos_printf("[cmiot] execute rsp failure\r\n");
			}
			cmiot_stream_table[i].exec_state = 0;
			if(cis_execute_rsp(-1, 2) != ZOS_EOK) return ZOS_ERROR;	
			
			return ZOS_EOK;	
		}
	}
	//返回 object 不在列表中
	return ZOS_ERROR;
}



/**
 * @brief 处理平台下发数据进行event上报
 *@param event_num        	[IN]     上报的事件ID
 *@retval #int   0 is success; other value is error
 */
static int cmiot_event_callback(int event_num)
{	
	zos_uint8_t retry_count=0;
	int ret = CIS_RET_OK;
	if(event_num == CIS_EVENT_UNREG_DONE)
	{
		cmiot_device_table.connect_state = cmiot_state_close;
		zos_printf("[cmiot] close success\r\n");
	}
	else if(event_num == CIS_EVENT_UPDATE_SUCCESS)
		zos_printf("[cmiot] updata success\r\n");
	else if(event_num == CIS_EVENT_UPDATE_FAILED)
		zos_printf("[cmiot] updata fail\r\n");
	else if(event_num == CIS_EVENT_REG_TIMEOUT)
		zos_printf("[cmiot] register timeout\r\n");
	else if(event_num == CIS_EVENT_REG_SUCCESS)
		zos_printf("[cmiot] register success\r\n");
	else if(event_num == CIS_EVENT_NOTIFY_SUCCESS)
		zos_printf("[cmiot] notify success\r\n");
	else if(event_num == CIS_EVENT_NOTIFY_FAILED)
		zos_printf("[cmiot] notify fail\r\n");
	else if(event_num == CIS_EVENT_UPDATE_NEED)
	{
		zos_printf("[cmiot] need updata\r\n");
		cmiot_update_time( 0);
	}
	if(cmiot_event_mq != NULL)
    {
        cmiot_event_msg_t *msg = ZOS_NULL;
        msg = zos_zalloc(sizeof(cmiot_event_msg_t));
        msg->id = event_num;
		zos_mq_send(cmiot_event_mq, &msg, 0, ZOS_WAITING_FOREVER);
    }
	return ret;
}


int cmiot_parameter_callback(int instance,int msgid,int result)
{


		return 0;
}


/*************************************************************
*	函数名称：	cmiot_clear_environment
*
*	函数功能：	清理cmiot运行环境
*
*	入口参数：	无
*
*	返回参数：	0：成功  1：失败
*
*	说明：		
*************************************************************/
zos_err_t cmiot_clear_environment(void)
{	
	memset(&cmiot_device_table,0,sizeof(cmiot_device_table));		 	//清空数据流结构体
	memset(&cmiot_stream_table,0,sizeof(cmiot_stream_table));		 	//清空数据流结构体

	return ZOS_EOK;
}





/**
 * @brief 用户下行数据输处理函数，不能阻塞
 *@param type        	[IN]     云平台下发请求类型
 *@param context        [IN]     云平台下发请求的上下文
 *@param uri            [IN]     云平台下发请求URI
 *@param mid            [IN]     云平台下发请求消息ID
 *@param eid            [IN]     云平台下发请求事件ID
 *@param valueType      [IN]     云平台下发请求数据类型
 *@param value          [IN]     云平台下发请求数据内容
 *@param valueLen       [IN]     云平台下发请求数据长度
 */
void cmiot_downstream_cb(et_callback_type_t type, void* context,cis_uri_t* uri,cis_mid_t mid, cis_evt_t eid, int valueType,
char* value, int valueLen)
{
	(void) context;
	(void) mid;
	(void) valueType;

    if(cmiot_context_mq == ZOS_NULL)
    {
        return;
    }

	cis_pkt_msg *msg =ZOS_NULL;
	msg = zos_zalloc(sizeof(cis_pkt_msg) + valueLen + 1);
	msg->objId = uri->objectId;
	msg->insId = uri->instanceId;
	msg->resId = uri->resourceId;
	msg->type = type;
	msg->flag = uri->flag;
	msg->evtId = eid;

	if(value != ZOS_NULL && valueLen > 0)
	{
		memcpy(msg->data, value, valueLen);
		msg->data_len = valueLen;
	}

	zos_mq_send(cmiot_context_mq, &msg, 0, osWaitForever);
}


/**
 * @brief Demo任务的详细处理流程
 * @note 
 注册完成后会从消息队列中读取消息，根据不同的消息类型进行响应，支持的消息类型请参考et_callback_type_t
 *@retval #int   0
 */
static int cmiot_demo_pro()
{
	int ret = CIS_RET_OK;
    cis_pkt_msg *rcv_msg = ZOS_NULL;
	int evtType = -1;
	while(cmiot_device_table.connect_state != cmiot_state_unreg)
	{	
		if(zos_mq_recv(cmiot_context_mq, &rcv_msg, 0, ZOS_WAITING_FOREVER) != ZOS_EOK )
		{
			continue;
		}
		evtType	= (int)rcv_msg->type;
		//when do closing,only can proc CALLBACK_TYPE_EVENT type  
		if(cmiot_device_table.connect_state == cmiot_state_close && evtType != CALLBACK_TYPE_EVENT)
		{
			zos_free(rcv_msg);
			continue;
		}
		switch(evtType)
		{
			case CALLBACK_TYPE_DISCOVER:
				ret = cmiot_discover_callback(-1,rcv_msg->objId);
				break;
			case CALLBACK_TYPE_OBSERVE:
				ret = cmiot_observe_callback(-1, rcv_msg->flag, rcv_msg->objId, rcv_msg->insId, rcv_msg->resId, 1);
				break;
			case CALLBACK_TYPE_OBSERVE_CANCEL:
				//Process observe cancel event
				cis_observe_rsp(-1, 1);
				break;
			case CALLBACK_TYPE_READ:
				//Process read event and send readRsp
				ret = cmiot_read_callback(-1, rcv_msg->objId, rcv_msg->insId, rcv_msg->resId, rcv_msg->flag);
				break;
			case CALLBACK_TYPE_WRITE:
				//Process write event and send writeRsp
				ret = cmiot_write_callback(-1,rcv_msg->objId, rcv_msg->insId, rcv_msg->resId,rcv_msg->data_len,&rcv_msg->data);
				break;
			case CALLBACK_TYPE_EXECUTE:
				//Process execute event and send executeRsp
				ret = cis_execute_rsp(-1, 2);
				break;
			case CALLBACK_TYPE_OBSERVE_PARAMS:
				//Process parameter event and send parameterRsp
				ret = cis_rsp_withparam(-1, 2);
				break;
			case CALLBACK_TYPE_EVENT:
				//Process event inform and try to update
				ret = cmiot_event_callback(rcv_msg->evtId);	
				break;
			case CALLBACK_TYPE_NOTIFY:
				//Process send notify event
				ret = cis_notify_sync(-1, rcv_msg->objId, rcv_msg->insId, rcv_msg->resId, rcv_msg->valueType,
				rcv_msg->data_len,rcv_msg->data, rcv_msg->index, rcv_msg->flag, cmiot_device_table.notify_ack);
				break;
			case CALLBACK_TYPE_QUIT:
				//Process 
				cmiot_device_table.connect_state = cmiot_state_close;
				//do delete
				if (cmiot_close() != ZOS_EOK)
				{
					zos_task_delay(1000);
					if (cmiot_close() != ZOS_EOK)
					{
						zos_printf("[cmiot] delete error\r\n");
					}
				}
				break;
			default:
				break;			

		}
		zos_free(rcv_msg);	

		if(evtType != CALLBACK_TYPE_WRITE && ret != CIS_RET_OK)
		{
			ZOS_ASSERT(0);
		}
		
	}
	return 0;
}

/**
 * @brief Demo任务的处理流程入口
 * @note 参考任务自动创建cmiot套件，添加了默认的3311对象并使用默认参数向云平台发起注册
 */
static void cmiot_task(void *parameter)
{
	(void) parameter;

	//运行cmiot处理任务
	cmiot_demo_pro();
	cmiot_close_callback();
out:
    //删除下行报文回调函数
    cis_set_downstream_cb(ZOS_NULL);
	cmiot_task_handle = ZOS_NULL;
	zos_task_exit();
}




/***********************************************************
*	函数名称：	cmiot_init_environment
*
*	函数功能：	初始化cmiot运行环境
*
*	入口参数：	无
*
*	返回参数：	无
*
*	说明：		
***********************************************************/
int cmiot_init_environment(void)
{
	if(cmiot_context_mq == ZOS_NULL)
		cmiot_context_mq = zos_mq_create(50,sizeof(void *));
	if(cmiot_event_mq == ZOS_NULL)
		cmiot_event_mq = zos_mq_create(50,sizeof(void *));
	//注册平台下行报文回调函数
	cis_set_downstream_cb(cmiot_downstream_cb);
		//创建cmiot任务
    if(cmiot_task_handle == ZOS_NULL)
    {
		cmiot_task_handle = zos_task_create("cis_task",cmiot_task,ZOS_NULL,0x800,task_Priority_Normal1);
    }
    else
	{
		zos_printf("[cmiot] task running\r\n");
	}
        
	memset(&cmiot_device_table,0,sizeof(cmiot_device_table));	//清空数据流结构体
	cmiot_device_table.dev_len = 0;
	cmiot_device_table.lifetime = CMIOT_LIFE_TIME;
	cmiot_device_table.connect_state = cmiot_state_init;			//cmiot连接状态初始化
	cmiot_device_table.observercount = 0;
	cmiot_device_table.discovercount = 0;
	return ZOS_EOK;
}



#endif


